# 比较与拷贝

if __name__ == '__main__':
    # ==操作符比较对象之间的值是否相等
    a = 1
    b = 1
    print(f'a == b: {a == b}')

    # is操作符比较的是对象的身份标识是否相等,即它们是否是同一个对象,是否指向同一个内存地址
    # 在Python中,每个对象的身份标识,都能通过函数id(object)获得。因此,is操作符,相当于比较对象之间的ID是否相等
    print(f'id of a is: {id(a)}')
    print(f'id of b is: {id(b)}')
    print(f'a is b: {a is b}')

    # 在实际使用中,大多数情况下都是使用==来比较两个变量的值是否相等
    # 但是,当我们比较一个变量与一个单例(singleton)时,通常会使用is
    # 一个典型的例子,就是检查一个变量是否为None
    a = None
    if a is None:
        print('a is None')
    else:
        print(f'a = {a}')

    # 比较操作符is的执行效率通常要优于==,因为is不能被重载,Python就不需要先去寻找程序中是否有其他地方重载了比较操作符,之后去调用
    # is仅仅就是比较两个变量的ID是否相等
    # 但是==操作符却不同,执行a==b相当于是去执行a.__eq__(b),而Python大部分的数据类型都会去重载__eq__这个函数,其内部的处理通常会复杂一些
    # 比如,对于列表List,__eq__函数会去遍历列表中的元素,比较它们的顺序和值是否相等

    # 对于不可变(immutable)的变量的比较结果可能会发生改变
    # 例如元组tuple:虽然tuple是不可变的,但是tuple可以嵌套,如果tuple中嵌套了一个list,但是list中的元素发生了修改,那么这个tuple也就发生了修改
    t1 = (1, 2, [3, 4, 5])
    t2 = (1, 2, [3, 4, 5])
    print(f'before append, t1 == t2: {t1 == t2}')
    # 向t2内部的列表中添加一个元素,t1和t2的比较结果就变了
    t2[-1].append(6)
    print(f'after append, t1 == t2: {t1 == t2}')
